{ "cells": [ { "cell_type": "code", "execution_count": 99, "id": "saved-joseph", "metadata": {}, "outputs": [], "source": [ "# Solving systems of equations\n", "\n", "# To solve a system of equations, we will use the Python module\n", "# 'sympy' and the function 'linsolve'. We first have to tell Python which \n", "# variables we will be using. In this first trivial example, we will use \"x\" \n", "# as the variable.\n", "\n", "# Import sympy:\n", "from sympy import *" ] }, { "cell_type": "code", "execution_count": 100, "id": "distinct-corporation", "metadata": {}, "outputs": [], "source": [ "# Define our variable:\n", "x = Symbol('x')" ] }, { "cell_type": "code", "execution_count": 101, "id": "mighty-legislation", "metadata": {}, "outputs": [], "source": [ "# Next, we define our equation(s). It is assumed that the expression is \n", "# equal to zero. For example, the RHS of the equation is x - 2 and the LHS\n", "# is zero.\n", "eqn1 = x - 2" ] }, { "cell_type": "code", "execution_count": 102, "id": "incident-harvest", "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle \\left\\{\\left( 2,\\right)\\right\\}$" ], "text/plain": [ "FiniteSet((2,))" ] }, "execution_count": 102, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Now we can implement linsolve([...], [...]). In the first set of \n", "# square brackets, list the equations. In the second set of square brackets,\n", "# list the variables that you want to solve for.\n", "soln = linsolve([eqn1], [x])\n", "soln" ] }, { "cell_type": "code", "execution_count": 103, "id": "demographic-partnership", "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle \\left( 2,\\right)$" ], "text/plain": [ "(2,)" ] }, "execution_count": 103, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Python returns the solution as a `FiniteSet'. We can covert the FiniteSet\n", "# to list via:\n", "solnList = list(soln)[0]\n", "solnList" ] }, { "cell_type": "code", "execution_count": 104, "id": "noted-irish", "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle 2$" ], "text/plain": [ "2" ] }, "execution_count": 104, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Finally, we can index the list to get the final solution\n", "solnFinal = solnList[0]\n", "solnFinal" ] }, { "cell_type": "code", "execution_count": 105, "id": "dedicated-appraisal", "metadata": {}, "outputs": [], "source": [ "# Here's a less trivial system of two equations and two unknowns.\n", "# First, we need to define a second variable.\n", "y = Symbol('y')" ] }, { "cell_type": "code", "execution_count": 106, "id": "cooked-affairs", "metadata": {}, "outputs": [], "source": [ "# Here's the system of two equations and two unknowns.\n", "eqn1 = 10*x - 3*y - 5\n", "eqn2 = -2*x - 4*y - 7" ] }, { "cell_type": "code", "execution_count": 107, "id": "gorgeous-south", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x = -1/46 and y = -40/23\n" ] } ], "source": [ "# We now implement linsolve.\n", "soln = list(linsolve([eqn1, eqn2], [x, y]))[0];\n", "print('x =', soln[0], 'and y =', soln[1])" ] }, { "cell_type": "code", "execution_count": 108, "id": "adjusted-beijing", "metadata": {}, "outputs": [], "source": [ "# It is also possible to algebraically solve a system of equations in terms\n", "# of other variables. Below is a system of 6 complex equations and 6 unknowns.\n", "\n", "# The example below solves for the currents in an all-pass filter.\n", "# (Optional experiment in PHYS 231.)\n", "\n", "# We must define the six currents that we wish to solve for as variables as\n", "# well as the other relevant variables (R is resistance, C is capacitance,\n", "# L is inductance, v is voltage amplitude, and w is angular freqeuncy.\n", "v = Symbol('v')\n", "R = Symbol('R')\n", "w = Symbol('w')\n", "L = Symbol('L')\n", "C = Symbol('C')" ] }, { "cell_type": "code", "execution_count": 109, "id": "agricultural-finance", "metadata": {}, "outputs": [], "source": [ "# Here is a method to define all of six of the i0 to i5 symbols in a single line\n", "i0, i1, i2, i3, i4, i5 = symbols('i0:6')" ] }, { "cell_type": "code", "execution_count": 110, "id": "purple-blake", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(-1+0j)" ] }, "execution_count": 110, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Before we write our system of equations, first note that in Python you make\n", "# a number complex by following it with a 'j' (no space). For example,\n", "# to enter z = x + j*y we would type 'z = x + y*1j'. In these expressions\n", "# j represents sqrt(-1). Below we evaluate the square of of j which should\n", "# be equal to -1. \n", "1j**2" ] }, { "cell_type": "code", "execution_count": 111, "id": "federal-migration", "metadata": {}, "outputs": [], "source": [ "# To continue an input on a new line, use the backslash notation.\n", "eqns = [i0 - i1 - i2, i1 - i3 - i4, i2 + i4 - i5,\\\n", " i0*R + 1j*w*i1*L + i4*R + 1j*w*i5*L - v,\\\n", " i0*R + i2/(1j*w*C) + 1j*w*i5*L - v, i3/(1j*w*C) - i4*R - 1j*w*i5*L]" ] }, { "cell_type": "code", "execution_count": 112, "id": "polished-rocket", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{i0: (I*C*L*v*w**2 + 2.0*C*R*v*w - I*v)/(2.0*I*C*L*R*w**2 + 2.0*C*R**2*w + 2.0*L*w - 2.0*I*R),\n", " i1: I*v/(-2.0*L*w + 2.0*I*R),\n", " i2: -C*v*w/(-2.0*C*R*w + 2.0*I),\n", " i3: C*v*w/(2.0*C*R*w - 2.0*I),\n", " i4: (-I*C*L*v*w**2 - I*v)/(2.0*I*C*L*R*w**2 + 2.0*C*R**2*w + 2.0*L*w - 2.0*I*R),\n", " i5: -v/(-2.0*I*L*w - 2.0*R)}" ] }, "execution_count": 112, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# For some reason, 'linsolve' doesn't work here. However, we can use 'solve'.\n", "soln = solve(eqns, [i0, i1, i2, i3, i4, i5])\n", "soln" ] }, { "cell_type": "code", "execution_count": 113, "id": "worst-shuttle", "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle \\frac{i C L v w^{2} + 2.0 C R v w - i v}{2.0 i C L R w^{2} + 2.0 C R^{2} w + 2.0 L w - 2.0 i R}$" ], "text/plain": [ "(I*C*L*v*w**2 + 2.0*C*R*v*w - I*v)/(2.0*I*C*L*R*w**2 + 2.0*C*R**2*w + 2.0*L*w - 2.0*I*R)" ] }, "execution_count": 113, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# As you can see the solutions is very complicated! \n", "\n", "# The output of 'solve' is an object called a 'Python dictionary'.\n", "# The individual solutions can be accessed using soln[i0], soln[i1], ...\n", "# Here is the solution for i0:\n", "soln[i0]" ] }, { "cell_type": "code", "execution_count": 114, "id": "sporting-following", "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle 3.75829862092635 \\cdot 10^{-8} \\left(2.51327412287183 + 0.579136704174297 i\\right) \\left(5026.54824574367 - 1158.27340834859 i\\right)$" ], "text/plain": [ "3.75829862092635e-8*(2.51327412287183 + 0.579136704174297*I)*(5026.54824574367 - 1158.27340834859*I)" ] }, "execution_count": 114, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# We can use 'subs([],[],[],...)' to enter in numerical values for the various\n", "# symbols. I'll import 'numPy' too so that we can access pi. Here is a numerical\n", "# value of i0.\n", "import numpy as np\n", "i0num = soln[i0].subs([(v, 1), (C, 10e-9), (L, 10e-3), (R, 1000), (w, 2*np.pi*20e3)])\n", "i0num" ] }, { "cell_type": "code", "execution_count": 115, "id": "coordinated-practice", "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle 0.0005$" ], "text/plain": [ "0.000500000000000000" ] }, "execution_count": 115, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# We can force Python to tidy up the number using 'N()'.\n", "N(i0num)" ] }, { "cell_type": "code", "execution_count": 116, "id": "collective-disposition", "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle 0.0005$" ], "text/plain": [ "0.000500" ] }, "execution_count": 116, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# We can use an option with N() to specify how many sig figs to keep. In the \n", "# output, the numerical value shows only 1 sig. fig. because it is exact.\n", "N(i0num, 3)" ] }, { "cell_type": "code", "execution_count": 117, "id": "timely-tender", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "i0 = 0.000500\n", "i1 = 0.000194 - 0.000244*I\n", "i2 = 0.000306 + 0.000244*I\n", "i3 = 0.000306 + 0.000244*I\n", "i4 = -0.000112 - 0.000487*I\n", "i5 = 0.000194 - 0.000244*I\n" ] } ], "source": [ "# Here are numerical values for all six of the currents.\n", "print('i0 =', N(soln[i0].subs([(v, 1), (C, 10e-9), (L, 10e-3), (R, 1000), (w, 2*np.pi*20e3)]), 3))\n", "print('i1 =', N(soln[i1].subs([(v, 1), (C, 10e-9), (L, 10e-3), (R, 1000), (w, 2*np.pi*20e3)]), 3))\n", "print('i2 =', N(soln[i2].subs([(v, 1), (C, 10e-9), (L, 10e-3), (R, 1000), (w, 2*np.pi*20e3)]), 3))\n", "print('i3 =', N(soln[i3].subs([(v, 1), (C, 10e-9), (L, 10e-3), (R, 1000), (w, 2*np.pi*20e3)]), 3))\n", "print('i4 =', N(soln[i4].subs([(v, 1), (C, 10e-9), (L, 10e-3), (R, 1000), (w, 2*np.pi*20e3)]), 3))\n", "print('i5 =', N(soln[i5].subs([(v, 1), (C, 10e-9), (L, 10e-3), (R, 1000), (w, 2*np.pi*20e3)]), 3))" ] }, { "cell_type": "code", "execution_count": null, "id": "abroad-retirement", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" } }, "nbformat": 4, "nbformat_minor": 5 }